package the.bytecode.club.bytecodeviewer.gui.resourcelist;

import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Enumeration;

/***************************************************************************
 * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite        *
 * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com  *
 *                                                                         *
 * This program is free software: you can redistribute it and/or modify    *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation, either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 ***************************************************************************/

/**
 * @author Konloch
 * @since 6/22/2021
 */
public class SearchKeyAdapter extends KeyAdapter {
  private final ResourceListPane resourceListPane;

  public SearchKeyAdapter(ResourceListPane resourceListPane) {
    this.resourceListPane = resourceListPane;
  }

  @Override
  public void keyPressed(final KeyEvent ke) {
    //only trigger on enter
    if (ke.getKeyCode() != KeyEvent.VK_ENTER)
      return;

    String qt = resourceListPane.quickSearch.getText();

    if (qt.trim().isEmpty()) //NOPE
      return;

    String[] path;

    path = qt.split("[\\./]+"); // split at dot or slash
    qt = qt.replace('/', '.');

    ResourceTreeNode curNode = resourceListPane.treeRoot;
    boolean caseSensitive = resourceListPane.caseSensitive.isSelected();

    boolean success = false;
    if (resourceListPane.exact.isSelected()) {
      pathLoop:
      for (int i = 0; i < path.length; i++) {
        final String pathName = path[i];
        final boolean isLast = i == path.length - 1;

        for (int c = 0; c < curNode.getChildCount(); c++) {
          final ResourceTreeNode child = (ResourceTreeNode) curNode.getChildAt(c);
          Object userObject = child.getUserObject();
          if (caseSensitive ? userObject.toString().equals(pathName) : userObject.toString().equalsIgnoreCase(pathName)) {
            curNode = child;
            if (isLast) {
              final TreePath pathn = new TreePath(curNode.getPath());
              resourceListPane.tree.setSelectionPath(pathn);
              resourceListPane.tree.makeVisible(pathn);
              resourceListPane.tree.scrollPathToVisible(pathn);
              resourceListPane.openPath(pathn); //auto open
              success = true;
              break pathLoop;
            }
            continue pathLoop;
          }
        }
        System.out.println("Could not find " + pathName);
        break;
      }
    } else {
      @SuppressWarnings("unchecked")
      Enumeration<TreeNode> enums = curNode.depthFirstEnumeration();
      while (enums != null && enums.hasMoreElements()) {
        ResourceTreeNode node = (ResourceTreeNode) enums.nextElement();
        if (node.isLeaf()) {
          String userObject = (String) (node.getUserObject());
          String lastElem = path[path.length - 1];

          if (caseSensitive ? userObject.contains(lastElem) : userObject.toLowerCase().contains(lastElem.toLowerCase())) {
            TreeNode[] pathArray = node.getPath();
            int k = 0;
            StringBuilder fullPath = new StringBuilder();
            while (pathArray != null
                    && k < pathArray.length) {
              ResourceTreeNode n = (ResourceTreeNode) pathArray[k];
              String s = (String) (n.getUserObject());
              fullPath.append(s);
              if (k++ != pathArray.length - 1) {
                fullPath.append(".");
              }
            }
            String fullPathString = fullPath.toString();

            if (caseSensitive ? fullPathString.contains(qt) : fullPathString.toLowerCase().contains(qt.toLowerCase())) {
              final TreePath pathn = new TreePath(node.getPath());
              resourceListPane.tree.setSelectionPath(pathn.getParentPath());
              resourceListPane.tree.setSelectionPath(pathn);
              resourceListPane.tree.makeVisible(pathn);
              resourceListPane.tree.scrollPathToVisible(pathn);
              success = true;
              break;
            }
          }
        }
      }

    }

    if (!success) {
      Toolkit.getDefaultToolkit().beep();
    }
  }
}
